#include "stdafx.h"
#include "sphere.h"

bool is_valid(const SphereStream& info)
{
	return info.block_count >= 0;
}

bool is_valid(const IntersectRayWithSpheresInfo& info)
{
	return info.rays != nullptr &&
		info.spheres != nullptr &&
		info.intersection_stream_offset >= 0 &&
		info.ray_blocks_count > 0 &&
		info.sphere_blocks_count > 0;
}
void intersect_ray_block_with_sphere_block();
void intersect_rays_with_spheres(const IntersectRayWithSpheresInfo& info)
{
	auto inv_two_a = simd::c_0_5;

	assert(is_valid(info));
	for(int ray_block_i = 0; ray_block_i < info.ray_blocks_count; ray_block_i++)
	{
		auto ray_origins_block = info.rays->origins.block(ray_block_i);
		auto ray_directions_block = info.rays->directions.block(ray_block_i);

		f32block intersection_t;
		v3block intersection_position;
		v3block intersection_normal;
	
		for(int sphere_block_i = 0; sphere_block_i < info.sphere_blocks_count; sphere_block_i++)
		{
			auto sphere_origins_block = info.spheres->origins.block(sphere_block_i);
			auto sphere_radii_block = info.spheres->radii.block(sphere_block_i);
		
			auto dp = ray_origins_block - sphere_origins_block;
			auto r = dot(dp, ray_directions_block);
			auto b = simd::c_2 * r;
			auto c = dot(dp, dp) - sphere_radii_block * sphere_radii_block;

			auto d = sqrt(b * b - simd::c_2 * c);

			auto t0 = simd::c_neg_1 * (b - d) * inv_two_a;

			auto t1 = simd::c_neg_1 * (b + d) * inv_two_a;

			auto intersects = t0 > simd::c_0 | t1 > simd::c_0;

			t0 = t0 + (t0 <= simd::c_0) & simd::c_inf;
			t1 = t1 + (t1 <= simd::c_0) & simd::c_inf;
			auto t = min(t0, t1);
			
			auto use_current = t < intersection_t;
			auto not_use_current = t >= intersection_t;
			
			intersection_t = use_current & t + not_use_current & intersection_t;

			intersection_position = ray_directions_block * intersection_t + ray_origins_block;
			auto n = intersection_position - sphere_origins_block;
			intersection_normal = (n & use_current) + (intersection_normal & not_use_current);

			intersection_position = ray_directions_block * t + ray_origins_block;
			intersection_normal = intersection_position - sphere_origins_block; //normalize at the end

		}
		

		info.intersections->position.set_block(ray_block_i, intersection_position);
		intersection_normal = normalize(intersection_normal);
		info.intersections->surface_normal.set_block(ray_block_i, intersection_normal);
	}
}